using System;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Arroguella.Screens;

namespace Arroguella
{
    /// <summary>
    /// This is the main type for your game
    /// </summary>
    public class Arroguella : Game
    {
        #region Constructors

        /// <summary>
        /// Default constructor for the main game
        /// </summary>
        public Arroguella()
        {
            Graphics = new GraphicsDeviceManager(this);

            // Set the size
            Graphics.PreferredBackBufferHeight = 720;
            Graphics.PreferredBackBufferWidth = 1280;

            Content.RootDirectory = "Content";
        }

        #endregion

        #region Events

        /// <summary>
        /// This event is fired when the Title screen is returning control back to the main game class
        /// </summary>
        public void TitleScreenEvent(object obj, EventArgs e)
        {
            // Switch to the game screen
            CurrentScreen = GameScreen;
            IsFixedTimeStep = true;
            TargetElapsedTime = new TimeSpan(0, 0, 0, 0, 125); // 125ms = 8fps
        }

        /// <summary>
        /// This even is fired when GameScreen is returning control back to the main game class
        /// </summary>
        public void GameScreenEvent(object obj, EventArgs e)
        {
            // Switch to the Title screen
            CurrentScreen = TitleScreen;
            IsFixedTimeStep = false;
            TargetElapsedTime = new TimeSpan(0, 0, 0, 0, 50); // 50ms = 20fps
        }

        #endregion

        #region Methods

        /// <summary>
        /// Allows the game to perform any initialization it needs to before starting to run.
        /// This is where it can query for any required services and load any non-graphic
        /// related content.  Calling base.Initialize will enumerate through any components
        /// and initialize them as well.
        /// </summary>
        protected override void Initialize()
        {
            IsMouseVisible = true;

            #region Initialize Global Settings

            OldSchoolModeEnabled = true;

            string settingsMsg = string.Format("Old School Mode {0}\n", OldSchoolModeEnabled ? "ON" : "OFF");
            Console.WriteLine(settingsMsg);

            #endregion

            base.Initialize();
        }

        /// <summary>
        /// LoadContent will be called once per game and is the place to load
        /// all of your content.
        /// </summary>
        protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw textures.
            SpriteBatch = new SpriteBatch(GraphicsDevice);

            // Load the fonts
            Font = Content.Load<SpriteFont>("DefaultSpriteFont");
            PlayerInfoFont = Content.Load<SpriteFont>("PlayerInfoFont");

            //Initialize the various screens in the game
            TitleScreen = new TitleScreen(Content, new EventHandler(TitleScreenEvent), GraphicsDevice, this);
            GameScreen = new GameScreen(Content, new EventHandler(GameScreenEvent), GraphicsDevice, this);

            //Set the current screen
            CurrentScreen = TitleScreen;            
        }

        /// <summary>
        /// UnloadContent will be called once per game and is the place to unload
        /// all content.
        /// </summary>
        protected override void UnloadContent()
        {
            // TODO: Unload any non ContentManager content here
        }

        /// <summary>
        /// Allows the game to run logic such as updating the world,
        /// checking for collisions, gathering input, and playing audio.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Update(GameTime gameTime)
        {
            //By taking advantage of Polymorphism, we can call update on the current screen class, 
            //but the Update in the subclass is the one that will be executed.
            CurrentScreen.Update(gameTime);

            base.Update(gameTime);
        }

        /// <summary>
        /// This is called when the game should draw itself.
        /// </summary>
        /// <param name="gameTime">Provides a snapshot of timing values.</param>
        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.DimGray);

            // Start drawing
            SpriteBatch.Begin();

            //Again, using Polymorphism, we can call draw on teh current screen class
            //and the Draw in the subclass is the one that will be executed.
            CurrentScreen.Draw(SpriteBatch);

            // Stop drawing
            SpriteBatch.End();

            base.Draw(gameTime);
        }

        #endregion        

        #region Properties

        public GraphicsDeviceManager Graphics;

        public SpriteBatch SpriteBatch;

        public SpriteFont Font;

        public SpriteFont PlayerInfoFont;
   
        internal static TimeSpan KEY_PRESS_LIMIT = new TimeSpan(0, 0, 0, 0, 85);

        internal DateTime LastKeyPressTime = DateTime.Now;

        #region UI Elements

        public Rectangle TitleSafeArea { get { return GraphicsDevice.Viewport.TitleSafeArea; } }

        #region Screens
        
        public TitleScreen TitleScreen;
        public GameScreen GameScreen;
        public Screen CurrentScreen;

        #endregion
        
        #endregion

        #region Global Settings

        /// <summary>
        /// Old School Mode mimics the appearance of some of the very first roguelikes.
        /// </summary>
        public static bool OldSchoolModeEnabled { get; set; }

        #endregion

        #endregion
    }
}
